package gods.bubble.search;

import gods.bubble.common.StandardDocument;
import gods.bubble.util.Config;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.wltea.analyzer.lucene.IKSimilarity;

public class Searcher {
	private IndexSearcher normalSearcher;
	private IndexSearcher scholarSearcher;

	public static class Type {
		public static final int ALL = 0;
		public static final int NEWS = ALL + 1;
		public static final int SCHOLAR = NEWS + 1;
	}

	public Searcher(String indexDir, String scholarIndexDir) throws CorruptIndexException, IOException {
		normalSearcher = new IndexSearcher(FSDirectory.open(new File(indexDir)), true);
		scholarSearcher = new IndexSearcher(FSDirectory.open(new File(scholarIndexDir)), true);
		
		normalSearcher.setSimilarity(new IKSimilarity());
		scholarSearcher.setSimilarity(new IKSimilarity());
	}

	public SearchResult search(String query, int offset, int limit, int type)
			throws IOException, InvalidTokenOffsetsException {
		BooleanQuery bq = QueryLogicParser.logicalParse(query, type);
		
		Analyzer analyzer = new IKAnalyzer();
		IndexSearcher searcher = null;		
		TopDocs topDocs = null;
		
		if (type != Type.SCHOLAR) {
			searcher = normalSearcher;
		}
		else {
			searcher = scholarSearcher;
		}

		topDocs = searcher.search(bq, offset + limit);
		// System.out.println("Get " + topDocs.totalHits + " documents.");

		ScoreDoc[] scoreDocs = topDocs.scoreDocs;

		ArrayList<StandardDocument> allDocs = new ArrayList<StandardDocument>();

		for (int i = 0; i < scoreDocs.length; i++) {
			Document targetDoc = searcher.doc(scoreDocs[i].doc);

			StandardDocument current = new StandardDocument();

			current.url = targetDoc.get("url");
			current.title = targetDoc.get("title");
			current.content = targetDoc.get("content");

			TermQuery tq = new TermQuery(new Term("content", query));
			SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(
					"<span class=\"hightlight\">", "</span>");
			Highlighter highlighter = new Highlighter(simpleHTMLFormatter,
					new QueryScorer(tq));
			highlighter.setTextFragmenter(new SimpleFragmenter(50));

			if (current.content != null) {
				TokenStream tokenStream = analyzer.tokenStream("content",
						new StringReader(current.content));
				String[] highLightText = highlighter.getBestFragments(
						tokenStream, current.content, 1);

				if (highLightText != null) {
					StringBuilder sb = new StringBuilder();
					for (String hl : highLightText)
						sb.append(hl);

					current.content = sb.toString();
				}
			}

			current.lucene_score = topDocs.scoreDocs[i].score;
			current.pagerank = Double.valueOf(targetDoc.get("pagerank"));

			current.makeScore();

			allDocs.add(current);
		}

		Collections.sort(allDocs);

		ArrayList<StandardDocument> ret = new ArrayList<StandardDocument>();

		for (int i = offset; i < scoreDocs.length; i++) {
			StandardDocument current = allDocs.get(i);

//			System.out.println(current.title);
//			System.out.println(PathURL.url2path(current.url));
//			System.out.println(current.pagerank);
//			System.out.println(current.score);

			ret.add(current);
		}

		return new SearchResult(topDocs.totalHits, ret);
	}

	public static void main(String args[]) throws IOException,
			InvalidTokenOffsetsException {
		Searcher s = new Searcher(Config.indexDir, Config.scholarIndexDir);

		s.search("三言", 0, 10, Searcher.Type.SCHOLAR);
	}
}